package com.tjackson.TestApp;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class OrchAssemble {

    private static Logger logger= LoggerFactory.getLogger(OrchAssemble.class);

    /**
     * Json转换
     *
     * @param jsonMap 转换前JSON
     * @param chgInfoList 映射关系
     * @return 转换后JSON
     */
    public static  String convertJson(HashMap<String,String>jsonMap, List<ChgInfo> chgInfoList){
        String rtnJson="";
        if(chgInfoList == null){
            logger.error("映射关系表未设定");
            return jsonMap.get("input");
        }
        //分组                                                                                  这个是调用ChgInfo的getSrcJsonId方法
        Map<String,List<ChgInfo>> chgInfoMap=chgInfoList.stream().collect(Collectors.groupingBy(ChgInfo::getSrcJsonId));

        //按照分组执行
        for (Map.Entry<String,List<ChgInfo>> entry: chgInfoMap.entrySet()){
            rtnJson=convertJson(jsonMap.get(entry.getKey()),rtnJson,entry.getValue());
        }
        return rtnJson;

    }

    /**
     * 作者: LCG
     * 日期: 2021/4/16  18:31
     * 描述: 
     * @Param [jsonMap, chgInfoList]
     * @Return java.lang.String
     */
    public static  String convertJson2(HashMap<String,String>jsonMap, List<ChgInfo> chgInfoList){
        String rtnJson="";
        if(chgInfoList == null){
            logger.error("映射关系表未设定");
            return jsonMap.get("input");
        }
        //分组                                                                                  这个是调用ChgInfo的getSrcJsonId方法
        Map<String,List<ChgInfo>> chgInfoMap=chgInfoList.stream().collect(Collectors.groupingBy(ChgInfo::getSrcJsonId));

        //按照分组执行
        for (Map.Entry<String,List<ChgInfo>> entry: chgInfoMap.entrySet()){
            rtnJson=convertJson(jsonMap.get(entry.getKey()),rtnJson,entry.getValue());
        }
        return rtnJson;

    }


    /**
     * Json转换
     * @param inJson 转换前Json
     * @param outJson 转换后Json
     * @param chgInfoList 映射关系
     * @return 转换后JSON
     */
    public static String convertJson(String inJson, String outJson, List<ChgInfo> chgInfoList) {

        JSONObject inJsonObj = JSON.parseObject(inJson);
        JSONObject outJsonObj = JSON.parseObject(outJson);

        if (outJsonObj ==null){
            outJsonObj=new JSONObject();
        }
        for (ChgInfo chgInfo: chgInfoList){
            Object fromValue=getNodeValue(inJsonObj,chgInfo.getFrom());
            setNodeValue(outJsonObj,chgInfo.getTo(),fromValue);
        }
        return outJsonObj.toJSONString();
    }


    /**
     * 作者: LCG
     * 日期: 2021/4/16  18:32
     * 描述: 
     * @Param [inJson, outJson, chgInfoList]
     * @Return java.lang.String
     */
    public static String convertJson2(String inJson, String outJson, List<ChgInfo> chgInfoList) throws IOException {

        ObjectMapper objectMapper=new ObjectMapper();
        JsonNode inJsonNode = objectMapper.readTree(inJson);
        JsonNode outJsonNode1 = objectMapper.readTree(outJson);

        if (outJsonNode1 ==null){
            outJsonNode1=JsonNodeFactory.instance.objectNode();
        }

        for (ChgInfo chgInfo: chgInfoList){
            Object fromValue=getNodeValue2(inJsonNode,chgInfo.getFrom());
            setNodeValue2(outJsonNode1,chgInfo.getTo(),fromValue);
        }


        return objectMapper.writeValueAsString(outJsonNode1);
    }

    public static Object getNodeValue2(JsonNode inJsonNode , String node) {
        JsonNode target=inJsonNode;

        //获取节点的名称
        String[] arrNodeNm=trimAll(node).split("\\.");
        boolean isArrNode=false;
        String arrIdx="0";
        String strNode="";



        for (int i=0;i<arrNodeNm.length;i++){
            strNode=arrNodeNm[i];
            if("$".equalsIgnoreCase(strNode)){
                continue;
            }
            //数组节点判断
            isArrNode=isArrayNode(strNode);
            if (isArrNode){
                arrIdx=getNodeIdx(strNode);
                strNode=getNodeNm(strNode);
            }
            //取值
            if (i==arrNodeNm.length-1){
                if(inJsonNode.has(strNode)){
                    if (isArrNode){
                        JsonNode jsonNode = inJsonNode.withArray(strNode);
                        JsonNode jsonNode1 = jsonNode.get(arrIdx);
                        return jsonNode1;
                    }else{
                        JsonNode value = inJsonNode.findValue(strNode);
                        return value;
                    }
                }else{
                    return null;
                }
            }else{
                if (inJsonNode.has(strNode)){
                    if (isArrNode){
                        JsonNode jsonNode = inJsonNode.withArray(strNode);
                        target = jsonNode.get(arrIdx);
                    }else {
                        target =inJsonNode.findValue(strNode);
                    }
                }else {
                    return null;
                }
            }
        }
        return null;

    }

    public static void setNodeValue2(JsonNode outJsonObj , String node, Object value) throws IOException {
        ObjectMapper objectMapper=new ObjectMapper();
        JsonNode target=outJsonObj;
        boolean isArrNode;
        String arrIdx="0";
        String strNode;
        String[] arrNodeNm=trimAll(node).split("\\.");

        for (int i = 0; i < arrNodeNm.length; i++) {
            strNode=arrNodeNm[i];
            if("$".equalsIgnoreCase(strNode)){
                continue;
            }
            //数组节点判断
            isArrNode=isArrayNode(strNode);
            if (isArrNode){
                arrIdx=getNodeIdx(strNode);
                strNode=getNodeNm(strNode);
            }
            //设定对象
            if (i==arrNodeNm.length - 1){

                ObjectNode outJsonObj1 = (ObjectNode) target;
                String valueAsString = objectMapper.writeValueAsString(value);
                JsonNode jsonNode = objectMapper.readTree(valueAsString);
                outJsonObj1.set(strNode,jsonNode);
                target=outJsonObj1;
            }else{
                if (isArrNode){
                    ArrayNode arrTarget1=null;
                    if (target.has(strNode)){
                        JsonNode jsonNode = target.findValue(strNode);

                        if (jsonNode instanceof ArrayNode){
                            arrTarget1= (ArrayNode) jsonNode;
                        }else{
                            logger.error("=========映射关系设定有误:{}",node);
                            return;
                        }
                        //数组全部设定
                        if ("n".equalsIgnoreCase(arrIdx)){
                            String path = getJsonPath(i,arrNodeNm);
                            for (int j=0;j<arrTarget1.size();j++){
                                setNodeValue2(arrTarget1.get(j),path,value);
                            }
                            return;
                        }else{
                            for (int j=arrTarget1.size();j<Integer.parseInt(arrIdx)+1;j++){
                                JsonNode jsonNode1 = JsonNodeFactory.instance.objectNode();
                                arrTarget1.add(jsonNode1);
                            }
                            target= arrTarget1.get(Integer.valueOf(arrIdx));
                        }
                    }else {
                        if ("n".equalsIgnoreCase(arrIdx)){
                            logger.error("=======映射关系设定有误:{}",node);
                            return;
                        }
                        arrTarget1=JsonNodeFactory.instance.arrayNode();
                        //arrTarget=new JSONArray();
                        ObjectNode outJsonObj1 = (ObjectNode) target;
                        outJsonObj1.set(strNode,arrTarget1);
                        target=outJsonObj1;
                        //target.put(strNode,arrTarget);
                        for (int j=arrTarget1.size();j<Integer.parseInt(arrIdx)+1;j++){
                            //arrTarget.add(new JSONObject());
                            JsonNode jsonNode1 = JsonNodeFactory.instance.objectNode();
                            arrTarget1.add(jsonNode1);
                        }

                        target= arrTarget1.get(Integer.valueOf(arrIdx));
                    }
                }else {
                    if (target.has(strNode)){
                        target=target.findValue(strNode);
                    }else{
                        ObjectNode outJsonObj1 = (ObjectNode) target;
                        JsonNode jsonNode1 = JsonNodeFactory.instance.objectNode();
                        outJsonObj1.set(strNode,jsonNode1);
                        target=outJsonObj1;
                        target=target.findValue(strNode);

                    }
                }
            }
        }
    }


    /**
     * 设定节点值
     * @param jsonObject 对象Json
     * @param node  对象节点值
     * @param value 对象值
     */
    public static void setNodeValue(JSONObject jsonObject, String node, Object value) {
        JSONObject target=jsonObject;
        boolean isArrNode;
        String arrIdx="0";
        String strNode;
        String[] arrNodeNm=trimAll(node).split("\\.");

        for (int i = 0; i < arrNodeNm.length; i++) {
            strNode=arrNodeNm[i];

            if("$".equalsIgnoreCase(strNode)){
                continue;
            }
            //数组节点判断
            isArrNode=isArrayNode(strNode);
            if (isArrNode){
                arrIdx=getNodeIdx(strNode);
                strNode=getNodeNm(strNode);
            }
            //设定对象
            if (i==arrNodeNm.length - 1){
                if(target.containsKey(strNode)){
                    target.replace(strNode,value);
                }else{
                    target.put(strNode,value);
                }
            }else{
                if (isArrNode){
                    JSONArray arrTarget=null;
                    if (target.containsKey(strNode)){
                        Object arrObj = target.get(strNode);
                        if (arrObj instanceof JSONArray){
                            arrTarget= (JSONArray) arrObj;
                        }else{
                            logger.error("=========映射关系设定有误:{}",node);
                            return;
                        }
                        //数组全部设定
                        if ("n".equalsIgnoreCase(arrIdx)){
                            String path = getJsonPath(i,arrNodeNm);
                            for (int j=0;j<arrTarget.size();j++){
                                setNodeValue(arrTarget.getJSONObject(j),path,value);
                            }
                            return;
                        }else{
                            for (int j=arrTarget.size();j<Integer.parseInt(arrIdx)+1;j++){
                                arrTarget.add(new JSONObject());
                            }
                            target= (JSONObject) arrTarget.get(Integer.valueOf(arrIdx));
                        }
                    }else {
                        if ("n".equalsIgnoreCase(arrIdx)){
                            logger.error("=======映射关系设定有误:{}",node);
                            return;
                        }
                        arrTarget=new JSONArray();
                        target.put(strNode,arrTarget);
                        for (int j=arrTarget.size();j<Integer.parseInt(arrIdx)+1;j++){
                            arrTarget.add(new JSONObject());
                        }
                        target= (JSONObject) arrTarget.get(Integer.valueOf(arrIdx));
                    }
                }else {
                    if (target.containsKey(strNode)){
                        target=target.getJSONObject(strNode);
                    }else{
                        target.put(strNode,new JSONObject());
                        target=target.getJSONObject(strNode);
                    }
                }
            }
        }

    }


    /**
     *取得指定NODE值
     * @param jsonObject 对象Json
     * @param node 取得对象节点名
     * @return node值
     */
    public static Object getNodeValue(JSONObject jsonObject, String node) {
        JSONObject target=jsonObject;

        String[] arrNodeNm=trimAll(node).split("\\.");
        boolean isArrNode=false;
        String arrIdx="0";
        String strNode="";

        for (int i=0;i<arrNodeNm.length;i++){
            strNode=arrNodeNm[i];
            if("$".equalsIgnoreCase(strNode)){
                continue;
            }
            //数组节点判断
            isArrNode=isArrayNode(strNode);
            if (isArrNode){
                arrIdx=getNodeIdx(strNode);
                strNode=getNodeNm(strNode);
            }
            //取值
            if (i==arrNodeNm.length-1){
                if(target.containsKey(strNode)){
                    if (isArrNode){
                        JSONArray jsonArray = target.getJSONArray(strNode);
                        return jsonArray.get(Integer.valueOf(arrIdx));
                    }else{
                        return target.get(strNode);
                    }
                }else{
                    return null;
                }
            }else{
                if (target.containsKey(strNode)){
                    if (isArrNode){
                        JSONArray jsonArray = target.getJSONArray(strNode);
                        target = jsonArray.getJSONObject(Integer.valueOf(arrIdx));
                    }else {
                        target = target.getJSONObject(strNode);
                    }
                }else {
                    return null;
                }
            }
        }
        return null;
    }

    /**
     * 取得数组节点名
     *
     * @param node 对象Node名称
     * @return 数组节点名
     */
    public static String getNodeNm(String node) {
        String rtn="";
        String target=trimAll(node);
        if (target.endsWith("]")){
            for (int i=target.length()-1;i>=0;i--){
                if(target.charAt(i)=='['){
                    return target.substring(0,i);
                }
            }
        }else {
            rtn = node;
        }
        return rtn;
    }

    /**
     * 取得数组下标
     *
     * @param node 对象Node名称
     * @return 数组下标
     */
    public static String getNodeIdx(String node) {
          String rtn="";
          String target=trimAll(node);
          if (target.endsWith("]")){
              for (int i=target.length()-1;i>= 0;i--){
                  if (target.charAt(i) == '['){
                      return target.substring(i+1,target.length()-1);
                  }
              }
          }
          return rtn;
    }

    /**
     * 是否数组节名
     *
     * @param node 节点名
     * @return 数组节名
     */
    public static boolean isArrayNode(String node) {
        String target=trimAll(node);
        if (target.endsWith("]")){
            return true;
        }else {
            return false;
        }
    }

    /**
     * 消除全部空格
     *
     * @param target 消除对象
     * @return 消除后值
     */
    public static String trimAll(String target) {

        return StringUtils.replace(target," ","");
    }

    /**
     * 字符串转换
     *
     * @param target 转换对象
     * @return转换后字符串
     */
    public static String objToStr(Object target){
        if(target instanceof JsonNode){
            return ((JsonNode)target).asText();
        }else if(target instanceof ArrayNode){
            return ((ArrayNode)target).asText();
        }else {
            return (String) target;
        }
    }


    /**
     * 路径取得
     *
     * @param currIdx 下标
     * @param nodes 设定节点数组
     * @return 路径
     */
    public static String getJsonPath(int currIdx, String[] nodes) {
      StringBuffer strBuf=new StringBuffer();
      strBuf.append("$.");
      for (int j=currIdx+1;j<nodes.length;j++){
          if (j == nodes.length-1){
              strBuf.append(nodes[j]);
          }else {
              strBuf.append(nodes[j]).append(".");
          }
      }
        return strBuf.toString();
    }










}
